package Internet;

import javax.xml.crypto.Data;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

//回响服务器
//先接收请求，后发送响应
public class UdpEchoServer {

    //创建套接字，用于发送和接受数据报
    private DatagramSocket socket = null;

    public UdpEchoServer(int port) throws SocketException {
        //服务器使用固定端口号
        socket = new DatagramSocket(port);
        //socket不用close，因为socket是伴随服务器整个周期的，若服务器结束，就会释放PCB中的文件描述符表中的资源
    }

    public void start() throws IOException {
        System.out.println("服务器启动");

        //死循环，一直接收请求
        while (true) {
            //1.读取请求并解析
            //创建UDP数据报(接收请求)，字节数组保存载荷部分,length指定接收长度
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);

            //会产生阻塞，若客户端没有发送请求，就会阻塞，直到客户端请求发送
            socket.receive(requestPacket);

            //将读取的二进制数据构造成字符串
            //最后一个参数不能传4096，只是构造有效部分，接收的数据不可能将字节数组填满
            String request = new String(requestPacket.getData(), 0, requestPacket.getLength());

            //2.根据请求，计算响应
            //由于此处为回响服务器，客户端发过来什么数据，就回应什么数据
            String response = process(request);

            //3.把响应返回给客户端
            //将计算出的相应转化成字节数组，范围为0-response.getBytes().length，由于是有效长度，不能传4096
            //计算长度时不能使用response.length()，这样算出来的是字符串的长度
            //requestPacket.getSocketAddress()包含目的IP和目的端口
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),
                    0, response.getBytes().length, requestPacket.getSocketAddress());

            //发送数据
            socket.send(responsePacket);

            //打印日志
            System.out.printf("[%s:%d] request: %s, response: %s\n",
                    requestPacket.getAddress().toString(), requestPacket.getPort(),
                    request, response);
        }
    }

    //计算响应
    private String process(String request) {
        //回显服务器，直接返回，无需计算
        //根据计算方法来编写代码
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer udpEchoServer = new UdpEchoServer(9090);
        udpEchoServer.start();
    }
}
